home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’87 / Source ƒ.sit / Source ƒ / C ƒ / TRANS-LSC / EventLog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-08  |  15.5 KB  |  849 lines  |  [TEXT/KAHL]

  1. /*
  2.     EventLog - TransDisplay event-logging demonstration program
  3.  
  4.     The project should include EventLog.c (this file), TransDisplay.c
  5.     (or a project made from TransDisplay.c), TransSkel.c (or a project
  6.     made from TransSkel.c), and MacTraps.
  7.     
  8.     8 November 1986    Paul DuBois
  9. */
  10.  
  11.  
  12. # include    <EventMgr.h>
  13. # include    <MenuMgr.h>
  14. # include    <ControlMgr.h>
  15. # include    <FontMgr.h>
  16. # include    "TransDisplay.h"
  17.  
  18.  
  19. enum                    /* declare zoom box part codes */
  20. {
  21.     inZoomIn = 7,
  22.     inZoomOut
  23. };
  24.  
  25.  
  26. # define    maxButton    14
  27.  
  28.  
  29. # define    helpTextRes        1000    /* help text resource number */
  30. # define    aboutAlrtRes    1000    /* About... alert resource number */
  31.  
  32.  
  33. typedef enum                    /* Menu resource numbers */
  34. {
  35.     fileMenuRes = 1000,
  36.     editMenuRes,
  37.     logMenuRes
  38. };
  39.  
  40.  
  41. typedef enum                    /* Window resource numbers */
  42. {
  43.     logWindRes = 1000,
  44.     helpWindRes,
  45.     selectWindRes
  46. };
  47.  
  48.  
  49. typedef enum            /* File menu item numbers */
  50. {
  51.     showLog = 1,    /* make windows visible/bring to front */
  52.     showHelp,
  53.     showSelect,
  54.     /* --- */
  55.     quit = 5
  56. };
  57.  
  58.  
  59. typedef enum                /* Edit menu item numbers */
  60. {
  61.     undo = 1,
  62.     /* --- */
  63.     cut = 3,
  64.     copy,
  65.     paste,
  66.     clear
  67. };
  68.  
  69.  
  70. typedef enum                /* Log menu item numbers */
  71. {
  72.     logEvents = 1,        /* whether events are logged */
  73.     excludeLWind,
  74.     /* --- */
  75.     flushLog = 4,        /* flush log output */
  76.     /* --- */
  77.     wrapStyle = 6,        /* word wrap or not */
  78.     /* --- */
  79.     leftJust = 8,        /* justification */
  80.     centerJust,
  81.     rightJust,
  82.     /* --- */
  83.     small = 12,            /* text size */
  84.     medium,
  85.     large,
  86.     /* --- */
  87.     top = 16,            /* scroll home */
  88.     bottom                /* scroll to bottom */
  89. };
  90.  
  91.  
  92. typedef struct CtrlInfo
  93. {
  94.     Point            loc;        /* upper left of control */
  95.     Str255            title;        /* control title */
  96.     Boolean            *flagAddr;    /* associated boolean */
  97.     ControlHandle    ctrl;        /* associated control */
  98.     struct CtrlInfo    *subInfo;    /* subsidiary control */
  99.  
  100. } CtrlInfo;
  101.  
  102.  
  103. WindowPtr        selectWind;            /* event selection window */
  104. WindowPtr        helpWind;            /* help text window */
  105. WindowPtr        logWind;            /* log output window */
  106. MenuHandle        fileMenu;
  107. MenuHandle        editMenu;
  108. MenuHandle        logMenu;
  109. Boolean            reportEvents;        /* report events or not */
  110. Boolean            excludeLog;            /* exclude log window events or not */
  111. int                logFont;
  112. int                logSize;
  113. int                logWrap;
  114. int                logJust;
  115.  
  116.  
  117. Boolean                            /* event type selection flags */
  118.         rMouseDown = true,
  119.             rMouseMods = false,
  120.             rMouseWind = true,
  121.             rMouseLoc = false,
  122.             rMousePart = true,
  123.             rMouseSys = false,
  124.         rMouseUp = false,
  125.         rKeyDown = true,
  126.             rKDMods = false,
  127.         rAutoKey = true,
  128.             rAKMods = false,
  129.         rUpdate = true,
  130.         rActivate = true,
  131.         rDisk = true;
  132.  
  133.  
  134. /*
  135.     Control information.  The last field is used to tell which controls
  136.     are "owned" by another.  When the owner is unchecked, all the owned
  137.     controls go dim.
  138. */
  139.  
  140. CtrlInfo    ctrlInfo [maxButton] =
  141. {
  142.     { { 5, 10}, "\pMouse Down", &rMouseDown, nil, nil },
  143.     { { 25, 30}, "\pModifiers", &rMouseMods, nil, &ctrlInfo[0] },
  144.     { { 45, 30}, "\pWindow", &rMouseWind, nil, &ctrlInfo[0] },
  145.     { { 65, 30}, "\pLocation", &rMouseLoc, nil, &ctrlInfo[0] },
  146.     { { 85, 30}, "\pPart Code", &rMousePart, nil, &ctrlInfo[0] },
  147.     { { 105, 30}, "\pSystem Clicks", &rMouseSys, nil, &ctrlInfo[0] },
  148.     { { 125, 10}, "\pMouse Up", &rMouseUp, nil, nil },
  149.     { { 5, 160}, "\pKey Down", &rKeyDown, nil, nil },
  150.     { { 25, 180}, "\pModifiers", &rKDMods, nil, &ctrlInfo[7] },
  151.     { { 45, 160}, "\pAutoKey", &rAutoKey, nil, nil },
  152.     { { 65, 180}, "\pModifiers", &rAKMods, nil, &ctrlInfo[9] },
  153.     { { 85, 160}, "\pUpdate", &rUpdate, nil, nil },
  154.     { { 105, 160}, "\pActivate", &rActivate, nil, nil },
  155.     { { 125, 160}, "\pDisk", &rDisk, nil, nil }
  156. };
  157.  
  158. /*    Window that was in front last time checked    */
  159.  
  160. WindowPtr    lastFront = nil;
  161.  
  162.  
  163. /*
  164.     Print information about a window.  If it's a window with a title,
  165.     print the title.  Print whether it's a
  166.     desk accessory window.
  167. */
  168.  
  169. WindowInfo (theWind)
  170. WindowPeek    theWind;
  171. {
  172. Str255    title;
  173.  
  174.     GetWTitle (theWind, title);
  175.     if (title[0] != 0)            /* window has title */
  176.     {
  177.         DisplayChar (' ');
  178.         DisplayString (title);
  179.     }
  180.  
  181.     if (theWind->windowKind < 0)
  182.         DisplayString ("\p (DA)");
  183. }
  184.  
  185.  
  186. Modifiers (mods)
  187. int        mods;
  188. {
  189.     DisplayString ("\p mods (0x");
  190.     DisplayHexInt (mods);
  191.     DisplayChar (')');
  192. }
  193.  
  194.  
  195. MouseLoc (thePt, thePort)
  196. Point    thePt;
  197. GrafPtr    thePort;
  198. {
  199. GrafPtr    savePort;
  200.  
  201.     GetPort (&savePort);
  202.     SetPort (thePort);
  203.     GlobalToLocal (&thePt);
  204.     SetPort (savePort);
  205.     if (rMouseLoc)
  206.     {
  207.         DisplayString ("\p loc (");
  208.         DisplayInt (thePt.h);
  209.         DisplayString ("\p, ");
  210.         DisplayInt (thePt.v);
  211.         DisplayChar (')');
  212.     }
  213. }
  214.  
  215.  
  216. /*
  217.     Mouse click.  Get the window that the click occurred in, and the
  218.     part of the window.
  219.  
  220.     Make sure to get all the part codes!  (incl. zoom box stuff)
  221. */
  222.  
  223. ReportMouse (theEvent)
  224. EventRecord    *theEvent;
  225. {
  226. Point    evtPt;
  227. int        evtPart;
  228. GrafPtr    evtPort;
  229.  
  230.     evtPt = theEvent->where;
  231.     evtPart = FindWindow (evtPt, &evtPort);
  232.     if (excludeLog && evtPort == logWind)
  233.         return;
  234.     DisplayString ("\pMouse click");
  235.  
  236.     switch (evtPart)
  237.     {
  238.  
  239. /*
  240.     Click in a desk accessory window.
  241. */
  242.         case inSysWindow:
  243.             if (rMouseSys)
  244.             {
  245.                 if (rMousePart)
  246.                     DisplayString ("\p in system window:");
  247.                 if (rMouseWind)
  248.                     WindowInfo (evtPort);
  249.                 MouseLoc (evtPt, evtPort);
  250.             }
  251.             break;
  252.  
  253. /*
  254.     Click in desk top.
  255. */
  256.         case inDesk:
  257.             if (rMousePart)
  258.                 DisplayString ("\p in desktop");
  259.             break;
  260.  
  261. /*
  262.     Click in menu bar.
  263. */
  264.         case inMenuBar:
  265.             if (rMousePart)
  266.                 DisplayString ("\p in menu bar");
  267.             break;
  268.  
  269. /*
  270.     Click in grow box.
  271. */
  272.         case inGrow:
  273.             if (rMousePart)
  274.                 DisplayString ("\p in grow region:");
  275.             if (rMouseWind)
  276.                 WindowInfo (evtPort);
  277.             MouseLoc (evtPt, evtPort);
  278.             break;
  279.  
  280. /*
  281.     Click in title bar.
  282. */
  283.         case inDrag:
  284.             if (rMousePart)
  285.                 DisplayString ("\p in drag region:");
  286.             if (rMouseWind)
  287.                 WindowInfo (evtPort);
  288.             break;
  289.  
  290. /*
  291.     Click in close box.
  292. */
  293.         case inGoAway:
  294.             if (rMousePart)
  295.                 DisplayString ("\p in close box:");
  296.             if (rMouseWind)
  297.                 WindowInfo (evtPort);
  298.             break;
  299.  
  300. /*
  301.     Click in zoom-in box.
  302. */
  303.         case inZoomIn:
  304.             if (rMousePart)
  305.                 DisplayString ("\p in zoom-in box:");
  306.             if (rMouseWind)
  307.                 WindowInfo (evtPort);
  308.             break;
  309.  
  310. /*
  311.     Click in zoom-out box.
  312. */
  313.         case inZoomOut:
  314.             if (rMousePart)
  315.                 DisplayString ("\p in zoom-out box:");
  316.             if (rMouseWind)
  317.                 WindowInfo (evtPort);
  318.             break;
  319.  
  320. /*
  321.     Click in content region.
  322.  
  323.     (Might also check in in control, and if so, print control information)
  324. */
  325.         case inContent:
  326.             if (rMousePart)
  327.                 DisplayString ("\p in content region:");
  328.             if (rMouseWind)
  329.                 WindowInfo (evtPort);
  330.             MouseLoc (evtPt, evtPort);
  331.             break;
  332.  
  333.     }
  334.     if (rMouseMods)
  335.         Modifiers (theEvent->modifiers);
  336.     DisplayLn ();
  337. }
  338.  
  339.  
  340. ReportKey (what, c, mods, modFlag)
  341. int        what;
  342. char    c;
  343. int        mods;
  344. Boolean    modFlag;
  345. {
  346.     if (what == keyDown)
  347.         DisplayString ("\pKey down: char '");
  348.     else
  349.         DisplayString ("\pAutokey: char '");
  350.     DisplayChar (c);
  351.     DisplayString ("\p' ");
  352.     if (modFlag)
  353.         Modifiers (mods);
  354.     DisplayLn ();
  355. }
  356.  
  357.  
  358. ReportActivate (theWind, mods)
  359. WindowPtr    theWind;
  360. int            mods;
  361. {
  362.     if ((mods & activeFlag) != 0)
  363.         DisplayString ("\pActivate:");
  364.     else
  365.         DisplayString ("\pDeactivate:");
  366.     WindowInfo (theWind);
  367.     DisplayLn ();
  368. }
  369.  
  370.  
  371. ReportUpdate (theWind)
  372. WindowPtr    theWind;
  373. {
  374.     DisplayString ("\pUpdate:");
  375.     WindowInfo (theWind);
  376.     DisplayLn ();
  377. }
  378.  
  379.  
  380. /*
  381.     General event logger
  382. */
  383.  
  384. LogEvent (theEvt)
  385. EventRecord    *theEvt;
  386.  
  387. {
  388. register EventRecord    *theEvent;
  389. Point                    evtPt;
  390. GrafPtr                    evtPort;
  391. register int            evtPart;
  392. register char            evtChar;
  393. register int            evtMods;
  394. Rect                    r;
  395.  
  396.     if (reportEvents == false)
  397.         return (false);            /* don't do anything */
  398.     theEvent = theEvt;
  399.     evtPt = theEvent->where;
  400.     switch (theEvent->what)
  401.     {
  402.  
  403. /*
  404.     Mouse click.
  405. */
  406.         case mouseDown:
  407.             if (rMouseDown)
  408.                 ReportMouse (theEvent);
  409.             break;
  410.  
  411.         case mouseUp:
  412.             if (rMouseUp)
  413.                 DisplayString ("\pMouse up\r");
  414.             break;
  415.  
  416. /*
  417.     Key event.
  418. */
  419.         case keyDown:
  420.             if (excludeLog && FrontWindow () == logWind)
  421.                 break;
  422.             if (rKeyDown)
  423.             {
  424.                 evtChar = theEvent->message & charCodeMask;
  425.                 evtMods = theEvent->modifiers;
  426.                 ReportKey (keyDown, evtChar, evtMods, rKDMods);
  427.             }
  428.             break;
  429.  
  430.         case autoKey:
  431.             if (excludeLog && FrontWindow () == logWind)
  432.                 break;
  433.             if (rKeyDown)
  434.             {
  435.                 evtChar = theEvent->message & charCodeMask;
  436.                 evtMods = theEvent->modifiers;
  437.                 ReportKey (autoKey, evtChar, evtMods, rAKMods);
  438.             }
  439.             break;
  440.  
  441. /*
  442.     Update a window.  If it's an update for the log window, invalidate
  443.     it, because the message is written and will cause a scroll BEFORE
  444.     the window actually gets updated.  This means that part of what
  445.     needs redrawing will be scrolled out of the update region and won't
  446.     be redrawn properly.  Invalidating the entire port is wasteful but
  447.     makes sure the whole window can be drawn properly.
  448. */
  449.         case updateEvt:
  450.             if ((WindowPtr) theEvent->message == logWind)
  451.             {
  452.                 SetPort (logWind);
  453.                 InvalRect (&logWind->portRect);
  454.             }
  455.             if (excludeLog && (WindowPtr) theEvent->message == logWind)
  456.                 break;
  457.             if (rUpdate)
  458.                 ReportUpdate (theEvent->message);
  459.             break;
  460.  
  461. /*
  462.     Activate or deactivate a window.
  463. */
  464.         case activateEvt:
  465.             if (excludeLog && (WindowPtr) theEvent->message == logWind)
  466.                 break;
  467.             if (rActivate)
  468.                 ReportActivate (theEvent->message, theEvent->modifiers);
  469.             break;
  470.  
  471. /*
  472.     handle inserts of uninitialized disks
  473. */
  474.         case diskEvt:
  475.             if (rDisk)
  476.             {
  477.                 DisplayString ("\pDisk insertion");
  478.                 if (HiWord (theEvent->message) != noErr)
  479.                 {
  480.                     DisplayString ("\p (needs initializing)");
  481.                 }
  482.                 DisplayLn ();
  483.             }
  484.             break;
  485.  
  486.     }
  487.     return (false);
  488. }
  489.  
  490.  
  491. /*
  492.     Background procedure.  Check front window, reset edit menu if window
  493.     changes from an application window to a non-application window.
  494.     Disable the Edit menu whenever an application window is active,
  495.     enable it otherwise.
  496.     Also called whenever it is known that the active window has changed.
  497. */
  498.  
  499. CheckFront ()
  500. {
  501. WindowPtr    curWind;
  502. int            theKind;
  503. Boolean        lastIsApp = false,
  504.             curIsApp = false;
  505.  
  506.     curWind = FrontWindow ();
  507.     if (IsDWindow (lastFront) || lastFront == selectWind)
  508.         lastIsApp = true;
  509.     if (IsDWindow (curWind) || curWind == selectWind)
  510.         curIsApp = true;
  511.     if (lastFront != curWind)
  512.     {
  513.         if (IsDWindow (lastFront) || lastFront == selectWind)
  514.             lastIsApp = true;
  515.         if (IsDWindow (curWind) || curWind == selectWind)
  516.             curIsApp = true;
  517.         if (lastIsApp != curIsApp)
  518.         {
  519.             theKind = 0;
  520.             if (curWind != nil)
  521.                 theKind = ((WindowPeek) curWind)->windowKind;
  522.             if (curWind == nil || theKind < 0)    /* no window or DA in front */
  523.                 EnableItem (editMenu, 0);
  524.             else
  525.                 DisableItem (editMenu, 0);
  526.             DrawMenuBar ();
  527.         }
  528.         lastFront = curWind;
  529.     }
  530. }
  531.  
  532.  
  533. /* ------------------------------------------------------------ */
  534. /*            Event Selection Window Handler Routines                */
  535. /* ------------------------------------------------------------ */
  536.  
  537.  
  538. /*
  539.     Activate event procedure for both display windows and the checkbox
  540.     window.
  541. */
  542.  
  543. Activate (active)
  544. Boolean    active;
  545. {
  546.     CheckFront ();
  547. }
  548.  
  549. /*
  550.     Update window.  This is easy, just draw the controls.
  551. */
  552.  
  553. Update (resized)
  554. Boolean    resized;            /* ignored */
  555. {
  556.     DrawControls (selectWind);
  557. }
  558.  
  559.  
  560. /*
  561.     Handle hits in check boxes:
  562.     Toggle check box, sync the associated flag, and enable or disable
  563.     any subsidiary check boxes accordingly.  (Subsidiaries have
  564.     information in the control structure that points back to the owner
  565.     check box.)
  566.  
  567. */
  568.  
  569. Mouse (thePt, t, mods)
  570. Point    thePt;
  571. long    t;
  572. int        mods;
  573. {
  574. ControlHandle    ctl;
  575. CtrlInfo        *ci;
  576. Boolean            val;
  577. int                i;
  578.  
  579.     if (FindControl (thePt, selectWind, &ctl))
  580.     {
  581.         if (TrackControl (ctl, thePt, nil))
  582.         {
  583.             ci = (CtrlInfo *) GetCRefCon (ctl);
  584.             val = !GetCtlValue (ctl);
  585.             *(ci->flagAddr) = val;
  586.             SetCtlValue (ctl, val);
  587.         
  588.             /* enable/disable any subsidiaries */
  589.         
  590.             for (i = 0; i < maxButton; ++i)
  591.             {
  592.                 if (ctrlInfo[i].subInfo->ctrl == ci->ctrl)
  593.                     HiliteControl (ctrlInfo[i].ctrl, val ? 0 : 255);
  594.             }
  595.         }
  596.     }
  597. }
  598.  
  599.  
  600. /*
  601.     File menu handler
  602. */
  603.  
  604. DoFileMenu (item)
  605. int        item;
  606. {
  607.     switch (item)
  608.     {
  609.         case showHelp:
  610.             SelectWindow (helpWind);
  611.             ShowWindow (helpWind);
  612.             break;
  613.         
  614.         case showSelect:
  615.             SelectWindow (selectWind);
  616.             ShowWindow (selectWind);
  617.             break;
  618.         
  619.         case showLog:
  620.             SelectWindow (logWind);
  621.             ShowWindow (logWind);
  622.             break;
  623.         
  624.         case quit:
  625.             SkelWhoa ();
  626.             break;
  627.  
  628.     }
  629. }
  630.  
  631. /*
  632.     Put the right check marks in the Log menu
  633. */
  634.  
  635. SetLogMenu ()
  636. {
  637.     CheckItem (logMenu, logEvents, reportEvents);
  638.     CheckItem (logMenu, excludeLWind, excludeLog);
  639.     CheckItem (logMenu, wrapStyle, logWrap >= 0);
  640.     CheckItem (logMenu, leftJust, logJust == teJustLeft);
  641.     CheckItem (logMenu, centerJust, logJust == teJustCenter);
  642.     CheckItem (logMenu, rightJust, logJust == teJustRight);
  643.     CheckItem (logMenu, small, logSize == 9);
  644.     CheckItem (logMenu, medium, logSize == 12);
  645.     CheckItem (logMenu, large, logSize == 24);
  646. }
  647.  
  648.  
  649. /*
  650.     Set display style of log window
  651. */
  652.  
  653. SetStyle ()
  654. {
  655.     SetDWindowStyle (logWind, logFont, logSize, logWrap, logJust);
  656.     SetLogMenu ();
  657. }
  658.  
  659.  
  660. /*
  661.     Log menu handler
  662. */
  663.  
  664. DoLogMenu (item)
  665. int        item;
  666. {
  667.     switch (item)
  668.     {
  669.         case logEvents:
  670.             reportEvents = !reportEvents;
  671.             SetLogMenu ();
  672.             break;
  673.  
  674.         case excludeLWind:
  675.             excludeLog = !excludeLog;
  676.             SetLogMenu ();
  677.             break;
  678.  
  679.         case flushLog:
  680.             FlushDWindow (logWind, 32767L);
  681.             break;
  682.         
  683.         case wrapStyle:
  684.             logWrap = (logWrap >= 0 ? -1 : 0);
  685.             SetStyle ();
  686.             break;
  687.  
  688.         case leftJust:
  689.             logJust = teJustLeft;
  690.             SetStyle ();
  691.             break;
  692.  
  693.         case centerJust:
  694.             logJust = teJustCenter;
  695.             SetStyle ();
  696.             break;
  697.  
  698.         case rightJust:
  699.             logJust = teJustRight;
  700.             SetStyle ();
  701.             break;
  702.  
  703.         case small:
  704.             logFont = monaco;
  705.             logSize = 9;
  706.             SetStyle ();
  707.             break;
  708.  
  709.         case medium:
  710.             logFont = systemFont;
  711.             logSize = 12;
  712.             SetStyle ();
  713.             break;
  714.  
  715.         case large:
  716.             logFont = geneva;
  717.             logSize = 24;
  718.             SetStyle ();
  719.             break;
  720.  
  721.         case top:
  722.             SetDWindowPos (logWind, 0);
  723.             break;
  724.  
  725.         case bottom:
  726.             SetDWindowPos (logWind, 32767);
  727.             break;
  728.     }
  729. }
  730.  
  731.  
  732. /*
  733.     Handle selection of About… item from Apple menu
  734. */
  735.  
  736. DoAbout ()
  737. {
  738.     (void) Alert (aboutAlrtRes, nil);
  739. }
  740.  
  741.  
  742. /*
  743.     Dispose of event selection window (and controls)
  744. */
  745.  
  746. WClobber ()
  747. {
  748.     DisposeWindow (selectWind);
  749. }
  750.  
  751.  
  752.  
  753. /*
  754.     Create controls
  755. */
  756.  
  757. MakeControls (theWind)
  758. WindowPtr    theWind;
  759. {
  760. int            i;
  761. CtrlInfo    *ci;
  762. Rect        r;
  763.  
  764.     for (i = 0; i < maxButton; ++i)
  765.     {
  766.         ci = &ctrlInfo[i];
  767.         SetRect (&r, ci->loc.h, ci->loc.v,
  768.                     ci->loc.h + StringWidth (ci->title) + 30,
  769.                     ci->loc.v + 20);
  770.         ci->ctrl = NewControl (theWind, &r, ci->title, true,
  771.                             *(ci->flagAddr), 0, 1,
  772.                             checkBoxProc, ci);
  773.     }
  774.     ValidRect (&theWind->portRect);
  775. }
  776.  
  777.  
  778. main ()
  779. {
  780. Handle    h;
  781.  
  782.     SkelInit ();
  783.     SkelApple ("\pAbout EventLog…", DoAbout);
  784.  
  785.     fileMenu = GetMenu (fileMenuRes);
  786.     SkelMenu (fileMenu, DoFileMenu, nil);
  787.  
  788.     editMenu = GetMenu (editMenuRes);
  789.     DisableItem (editMenu, 0);
  790.     SkelMenu (editMenu, nil, nil);
  791.  
  792.     logMenu = GetMenu (logMenuRes);
  793.     SkelMenu (logMenu, DoLogMenu, nil);
  794.  
  795. /*
  796.     Create windows and install handlers.
  797. */
  798.  
  799.     SetDWindowNotify (nil, Activate);
  800.  
  801.     helpWind = GetNewDWindow (helpWindRes, -1L);
  802.     SetDWindowStyle (helpWind, 0, 0, 0, teJustLeft);
  803.  
  804.     h = GetResource ('TEXT', helpTextRes);    /* read help text */
  805.     HLock (h);                        /* lock it and write to window */
  806.     DisplayText (*h, GetHandleSize (h));
  807.     HUnlock (h);
  808.     ReleaseResource (h);            /* done with it, so goodbye */
  809.     SetDWindowPos (helpWind, 0);    /* scroll back to top */
  810.     ShowWindow (helpWind);
  811.  
  812.     logWind = GetNewDWindow (logWindRes, -1L);
  813.  
  814.     SkelEventHook (LogEvent);
  815.     reportEvents = true;
  816.     excludeLog = false;
  817.  
  818.     logFont = monaco;
  819.     logSize = 9;
  820.     logWrap = 0;
  821.     logJust = teJustLeft;
  822.     SetStyle ();
  823.     ShowWindow (logWind);
  824.  
  825.     selectWind = GetNewWindow (selectWindRes, nil, -1L);
  826.  
  827.     SkelWindow (selectWind,    /* the window */
  828.                 Mouse,        /* mouse click handler */
  829.                 nil,        /* key clicks are ignored */
  830.                 Update,        /* window updating procedure */
  831.                 Activate,    /* window activate/deactivate procedure */
  832.                 nil,        /* hide window */
  833.                 WClobber,    /* window disposal procedure */
  834.                 nil,        /* idle proc */
  835.                 true);        /* irrelevant */
  836.  
  837.     MakeControls (selectWind);
  838.  
  839. /*
  840.     Process events until user quits,
  841.     then clean up and exit
  842. */
  843.  
  844.     CheckFront ();
  845.     SkelBackground (CheckFront);
  846.     SkelMain ();
  847.     SkelClobber ();
  848. }
  849.